package handler

import (
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"gorm.io/gorm"
	"log"
	"net/http"
	"pro/global"
	"pro/internal/models"
	"pro/internal/params"
	"strconv"
)

func FollowCreate(c *gin.Context) {
	var follow models.FollowLog
	var req params.CreateFollowReq
	var err error
	var ui models.UserInfo

	// 绑定请求参数
	if err = c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	follow.UserId = req.UserId
	follow.DistId = req.DistId
	if err = global.DB.Create(&follow).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "关注失败: " + err.Error()})
		return
	}
	// 获取被关注者ID
	targetUserID := req.DistId

	// 从全局连接映射中获取已建立的连接
	node, exists := global.ClientMap[targetUserID]

	if !exists {
		// 被关注者未建立WebSocket连接
		log.Printf("用户 %d 未建立WebSocket连接，无法推送关注消息", targetUserID)
		c.JSON(http.StatusOK, gin.H{
			"message": "关注成功（对方未在线，未收到通知）",
			"follow":  follow,
		})
		return
	}
	// 推送关注消息
	message := global.Message{
		Content: "有新的用户关注了你",
	}
	if err := PushMessage(node, targetUserID, message); err != nil {
		log.Printf("推送消息失败: %v", err)
	}

	tx := global.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	if err = tx.Model(&ui).Where("user_id=?", req.UserId).
		UpdateColumn("fans", gorm.Expr("followCount+?", 1)).Error; err != nil {
		tx.Rollback()
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    400,
			"message": "关注数量更新失败",
		})
		return
	}

	if err = tx.Model(&ui).Where("dist_id=?", req.DistId).
		UpdateColumn("fans", gorm.Expr("fansCount+?", 1)).Error; err != nil {
		tx.Rollback()
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    400,
			"message": "粉丝数量更新失败",
		})
		return
	}

	tx.Commit()

	c.JSON(http.StatusOK, gin.H{
		"message": "关注成功并已通知对方",
		"follow":  follow,
	})
}

// 处理WebSocket连接
func HandleWebSocket(c *gin.Context) {
	userID, _ := strconv.Atoi(c.Query("user_id"))
	conn, err := global.Upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		return
	}

	node := global.Node{
		Conn: conn,
		Data: make(chan []byte, 50),
	}

	global.ClientMap[userID] = node

	// 启动goroutine发送消息
	go func() {
		defer func() {
			conn.Close()
			delete(global.ClientMap, userID)
		}()

		for data := range node.Data {
			if err := conn.WriteMessage(websocket.TextMessage, data); err != nil {
				break
			}
		}
	}()
}

// 推送消息给指定用户
func PushMessage(node global.Node, userID int, message global.Message) error {
	// 序列化消息
	data, err := json.Marshal(message)
	if err != nil {
		return err
	}

	// 通过通道发送消息，避免直接操作Conn（符合Node结构设计）
	select {
	case node.Data <- data:
		log.Printf("成功推送消息给用户 %d", userID)
		return nil
	default:
		return http.ErrBodyReadAfterClose
	}

}
